package chances.epg.api.controller;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import chances.epg.api.controller.model.ChannelInfo;
import chances.epg.api.controller.model.EpisodeInfo;
import chances.epg.api.controller.model.MutilResultResponse;
import chances.epg.api.controller.model.ProgramInfo;
import chances.epg.api.controller.model.ResultResponse;
import chances.epg.api.controller.model.ResultSetResponse;
import chances.epg.api.controller.model.ScheduleInfo;
import chances.epg.api.controller.model.SeriesInfo;
import chances.epg.commons.log.EpgLogFactory;
import chances.epg.commons.utils.RequestUtils;
import chances.epg.data.PageBean;
import chances.epg.entity.content.Album;
import chances.epg.entity.content.AlbumItem;
import chances.epg.entity.content.Channel;
import chances.epg.entity.content.EpgContent;
import chances.epg.entity.content.Episode;
import chances.epg.entity.content.Link;
import chances.epg.entity.content.Program;
import chances.epg.entity.content.Schedule;
import chances.epg.entity.content.Series;

@RestController
public class ContentDataController extends AbstractDataController {
	private static Logger logger = EpgLogFactory.getSystemLogger();

	/**
	 * 获取单剧集内容信息.
	 * 
	 * @param contentCode
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/vod/{contentCode}")
	public ResultResponse<ProgramInfo> getVod(@PathVariable String contentCode, ModelMap model, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		Program vod = null;
		//List<Media> medias = null;
		int result = SUCCESS;

		try {
			vod = contentService.getProrgamByCode(contentCode);
			/*
			if (vod == null) {
				result = OBJ_NOT_FOUND;
			} else {
				medias = contentService.getMediaOfProgram(contentCode);
			}
			*/
			if (vod == null) {
				result = OBJ_NOT_FOUND;
			}

		} catch (DataAccessException ex) {
			result = DB_ERROR;
			logger.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			logger.error(ex.getMessage(), ex);
		}

		return new ResultResponse<ProgramInfo>(result, new ProgramInfo(vod));
	}

	/**
	 * 获取专栏内容信息.
	 * 
	 * @param contentCode
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/album/{contentCode}")
	public MutilResultResponse getAlbum(@PathVariable String contentCode, ModelMap model, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		Album album = null;
		List<AlbumItem> items = null;
		PageBean pageBean = null;

		int result = SUCCESS;

		int size = RequestUtils.getParameter(request, "size", DEFAULT_SIZE);
		int pageIndex = RequestUtils.getParameter(request, "pageindex", 1);
		try {
			album = contentService.getAlbumByCode(contentCode);
			if (album == null) {
				result = OBJ_NOT_FOUND;
			} else {
				pageBean = this.createPageBean(size, pageIndex);
				items = contentService.getAlbumItems(contentCode, 0, pageBean);
			}

		} catch (DataAccessException ex) {
			result = DB_ERROR;
			logger.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			logger.error(ex.getMessage(), ex);
		}

		return new MutilResultResponse(result, album, items, pageBean);
	}

	/**
	 * 获取连续剧信息
	 * 
	 * @param contentCode
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/series/{contentCode}")
	public MutilResultResponse getSeries(@PathVariable String contentCode, ModelMap model, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		Series series = null;
		List<Episode> episodes = null;
		PageBean pageBean = null;

		int result = SUCCESS;

		try {
			series = contentService.getSeriesByCode(contentCode);
			if (series == null) {
				result = OBJ_NOT_FOUND;
			} else {
				int size = RequestUtils.getParameter(request, "size", 0);
				if (size > 0) {
					int pageIndex = RequestUtils.getParameter(request, "pageindex", 1);
					pageBean = this.createPageBean(size, pageIndex);
					episodes = contentService.getEpisodes(contentCode, series.getSeriesType(), pageBean);
				} else {
					episodes = contentService.getEpisodes(contentCode, series.getSeriesType());
				}
			}

		} catch (DataAccessException ex) {
			result = DB_ERROR;
			logger.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			logger.error(ex.getMessage(), ex);
		}
		
		List<EpisodeInfo> episodeInfoList = new ArrayList<EpisodeInfo>();
		for (Episode episode : episodes) {
			episodeInfoList.add(new EpisodeInfo(episode));
		}
		
		episodes.clear();
		episodes = null;

		return new MutilResultResponse(result, new SeriesInfo(series), episodeInfoList, pageBean);
	}
	
	/**
	 * 获取直播频道信息.
	 * 
	 * @param contentCode
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/live/{contentCode}")
	public ResultResponse<ChannelInfo> getLiveChannel(@PathVariable String contentCode, ModelMap model,
			HttpServletRequest request, HttpServletResponse response) throws IOException {
		Channel channel = null;
		
		int result = SUCCESS;

		try {
			channel = channelService.getChannelByCode(contentCode);
			if (channel == null) {
				result = OBJ_NOT_FOUND;
			}

		} catch (DataAccessException ex) {
			result = DB_ERROR;
			logger.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			logger.error(ex.getMessage(), ex);
		}

		return new ResultResponse<ChannelInfo>(result, new ChannelInfo(channel));
	}
	
	/**
	 * 获取直播频道信息.
	 * 
	 * @param contentCode
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/schedules/{contentCode}")
	public ResultSetResponse<ScheduleInfo> getSchedules(@PathVariable String contentCode, ModelMap model,
			HttpServletRequest request, HttpServletResponse response) throws IOException {
		Channel channel = null;
		List<Schedule> schedules = null;
		PageBean pageBean = null;

		int result = SUCCESS;

		try {
			channel = channelService.getChannelByCode(contentCode);
			if (channel == null) {
				result = OBJ_NOT_FOUND;
			} else {
				Date startTime = this.getStartTime(request);
				Date endTime = this.getEndTime(request, startTime);
				int size = RequestUtils.getParameter(request, "size", 0);
				if (size > 0) {
					int pageIndex = RequestUtils.getParameter(request, "pageindex", 1);
					pageBean = this.createPageBean(size, pageIndex);
					schedules = channelService.getSchedulesOfChannel(contentCode, startTime, endTime,pageBean);
				} else {
					schedules = channelService.getSchedulesOfChannel(contentCode, startTime, endTime);
				}
			}

		} catch (DataAccessException ex) {
			result = DB_ERROR;
			logger.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			logger.error(ex.getMessage(), ex);
		}
		
		List<ScheduleInfo> scheduleInfoList = new ArrayList<ScheduleInfo>();
		for (Schedule schedule : schedules) {
			scheduleInfoList.add(new ScheduleInfo(schedule));
		}
		
		schedules.clear();
		schedules = null;

		return new ResultSetResponse<>(result, scheduleInfoList,pageBean);
	}

	/**
	 * 获取直播频道信息.
	 * 
	 * @param contentCode
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/channel/{contentCode}")
	public ResultResponse<Channel> getChannel(@PathVariable String contentCode, ModelMap model,
			HttpServletRequest request, HttpServletResponse response) throws IOException {
		Channel channel = null;
		List<Schedule> schedules = null;

		int result = SUCCESS;

		try {
			channel = channelService.getChannelByCode(contentCode);
			if (channel == null) {
				result = OBJ_NOT_FOUND;
			} else {
				Date startTime = this.getStartTime(request);
				Date endTime = this.getEndTime(request, startTime);
				schedules = channelService.getSchedulesOfChannel(contentCode, startTime, endTime);
				channel.setSchedules(schedules);
			}

		} catch (DataAccessException ex) {
			result = DB_ERROR;
			logger.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			logger.error(ex.getMessage(), ex);
		}

		return new ResultResponse<Channel>(result, channel);
	}

	/**
	 * 获取所有频道信息.
	 * 
	 * @param contentCode
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/getAllChannel")
	public ResultResponse<Collection<Channel>> getAllChannel(ModelMap model, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		int result = SUCCESS;

		Collection<Channel> allChannels = null;
		try {
			allChannels = this.channelService.getChannleList();
		} catch (DataAccessException ex) {
			result = DB_ERROR;
			logger.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			logger.error(ex.getMessage(), ex);
		}

		return new ResultResponse<Collection<Channel>>(result, allChannels);
	}

	/**
	 * 获取外部链接信息.
	 * 
	 * @param contentCode
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/link/{contentCode}")
	public ResultResponse<Link> getLink(@PathVariable String contentCode, ModelMap model, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		Link link = null;
		int result = SUCCESS;

		try {
			link = contentService.getLinkByCode(contentCode);
			if (link == null) {
				result = OBJ_NOT_FOUND;
			}
		} catch (DataAccessException ex) {
			result = DB_ERROR;
			logger.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			logger.error(ex.getMessage(), ex);
		}
		return new ResultResponse<Link>(result, link);
	}
	
	/**
	 * 获取内容可用状态.
	 * 
	 * @param contentCode
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/enableStatus/{contentCode}")
	public ResultResponse<Boolean> isEnable(@PathVariable String contentCode, ModelMap model, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		Boolean status = false;
		int result = SUCCESS;
		String[] codes = {contentCode};
		List<EpgContent> contents = null;
		try {
			contents = contentService.findContentInCodes(codes);
			if (contents == null || contents.size() == 0) {
				result = OBJ_NOT_FOUND;
			} else {
				status = true;
			}

		} catch (DataAccessException ex) {
			result = DB_ERROR;
			logger.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			logger.error(ex.getMessage(), ex);
		}

		return new ResultResponse<Boolean>(result, status);
	}
	
	@RequestMapping(value = "/content/{contentType}/{contentCode}")
	public ResultResponse<Object> getContent(@PathVariable String contentType, @PathVariable String contentCode,
			ModelMap model, HttpServletRequest request, HttpServletResponse response) throws IOException {
		int result = SUCCESS;
		Object content = null;
		try {
			switch (contentType) {
			case VOD_TYPE:
			case SERIES2_TYPE:
				content = this.contentService.getProrgamByCode(contentCode);
				if(content == null) {
					content = this.contentService.getMediaOfProgram(contentCode);
				}
				break;
			case SERIES_TYPE:
				content = this.contentService.getSeriesByCode(contentCode);
				break;
			default:
				break;
			}
			
		} catch (DataAccessException ex) {
			result = DB_ERROR;
			logger.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			logger.error(ex.getMessage(), ex);
		}
		return new ResultResponse<Object>(result, content);
	}

	private Date getStartTime(HttpServletRequest request) {
		Date beginTime = null;
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

		String startTime = request.getParameter("begintime");
		if (StringUtils.isNotBlank(startTime)) {
			try {
				beginTime = dateFormat.parse(startTime);
			} catch (ParseException e) {
				logger.error(e.getMessage(), e);
			}
		}

		if (beginTime == null) {
			startTime = dateFormat.format(new Date());
			try {
				beginTime = dateFormat.parse(startTime);
			} catch (ParseException e) {
				logger.error(e.getMessage(), e);
			}
		}

		return beginTime;

	}

	private Date getEndTime(HttpServletRequest request, Date startTime) {
		Date endTime = null;
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

		String strEndTime = request.getParameter("endtime");
		if (StringUtils.isNotBlank(strEndTime)) {
			try {
				endTime = dateFormat.parse(strEndTime);
			} catch (ParseException e) {
				logger.error(e.getMessage(), e);
			}
		}

		if (endTime == null) {
			endTime = startTime;
		}

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(endTime);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		return calendar.getTime();
	}
}
